package org.jzoie;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.MultiReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.DefaultSimilarity;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import org.jzoie.sequece.Sequece;
import org.jzoie.sequece.Sequeces;
import org.jzoie.util.MemoryMap;
import org.jzoie.util.TransferToDocument;

import proj.zoie.api.ZoieException;
import proj.zoie.api.ZoieIndexReader;
import proj.zoie.api.DataConsumer.DataEvent;
import proj.zoie.api.indexing.ZoieIndexableInterpreter;
import proj.zoie.impl.indexing.DefaultIndexReaderDecorator;
import proj.zoie.impl.indexing.ZoieConfig;
import proj.zoie.impl.indexing.ZoieSystem;

public class ZoieDocument<T>
{
	public static String DIRPATH="/index/jzoie/";
	private String dirPath="/index/jzoie/";
	private Analyzer analyzer=null;
	private Class<T> cls=null;
	public ZoieDocument(Class<T> cls) 
	{
		this.cls=cls;
		dirPath=dirPath+"/"+cls.getSimpleName();
		File file=new File(dirPath);
		if (!file.exists())
		{
			file.mkdirs();
		}
	}
	public ZoieDocument(Class<T> cls,String path) 
	{
		this.cls=cls;
		DIRPATH=path;
		dirPath=path+"/"+cls.getSimpleName();
		File file=new File(dirPath);
		if (!file.exists())
		{
			file.mkdirs();
		}
	}
	public void add(T t)
	{
		
		if (t==null) {
			return;
		}
	 	List<ZoieIndexReader<IndexReader>> zoieReaderList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        ZoieSystem<IndexReader, T> zoieSystem=null;
        try {
			//get zoie system
        	 System.out.println("addDocuments start size="+1);
             File idxDir = new File(dirPath);
             // MyZoieDataInterpreter
             ZoieIndexableInterpreter<T> interpreter = new ZoieDataInterpreter<T>();
             //default
             DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
             
             ZoieConfig zoieConfig = new ZoieConfig();
             zoieConfig.setBatchDelay(1000);
             zoieConfig.setBatchSize(50000);
             zoieConfig.setAnalyzer(getAnalyzer());//
             zoieConfig.setSimilarity(new DefaultSimilarity());
             zoieConfig.setRtIndexing(true);
             zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
             zoieSystem.start();
             
            long batchVersion = 0;
            ArrayList<DataEvent<T>> eventList = new ArrayList<DataEvent<T>>();
     		Sequece sequece=Sequeces.getSequece(cls);
     		batchVersion=sequece.getCount();
     		MemoryMap.set(t.toString(),batchVersion);
	     	DataEvent<T> dataEvent=new DataEvent<T>(t,batchVersion+"");
	     	eventList.add(dataEvent);
	     	batchVersion++;
			sequece.setCount(batchVersion);
			Sequeces.update(sequece);
     		try {
     			zoieSystem.consume(eventList);
     			//zoieSystem.flushEventsToMemoryIndex(1500);
     			//zoieSystem.flushEvents(timeout)
     			//DataZoieSystem.getIndexingSystem().
     			 zoieSystem.getAdminMBean().flushToMemoryIndex();
     			 zoieSystem.getAdminMBean().flushToDiskIndex();
     		} catch (ZoieException e) {
     			e.printStackTrace();
     		}
        	
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            try {
                if (null != indexSearcher) 
                {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) 
                {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != zoieReaderList && !zoieReaderList.isEmpty()) 
                {
                   zoieSystem.returnIndexReaders(zoieReaderList);
                   zoieReaderList = null;
                }
                if (zoieSystem !=null)
                {
                	zoieSystem.shutdown();
                	zoieSystem.stop();
				}
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		
	}
	public void add(List<T> list)
	{
		
		if (list==null || (list.size()==0)) {
			return;
		}
	 	List<ZoieIndexReader<IndexReader>> zoieReaderList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        ZoieSystem<IndexReader, T> zoieSystem=null;
        try {
			//get zoie system
        	 System.out.println("addDocuments start size="+list.size());
             File idxDir = new File(dirPath);
             // MyZoieDataInterpreter
             ZoieIndexableInterpreter<T> interpreter = new ZoieDataInterpreter<T>();
             //default
             DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
             
             ZoieConfig zoieConfig = new ZoieConfig();
             zoieConfig.setBatchDelay(1000);
             zoieConfig.setBatchSize(50000);
             zoieConfig.setAnalyzer(getAnalyzer());//
             zoieConfig.setSimilarity(new DefaultSimilarity());
             zoieConfig.setRtIndexing(true);
             zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
             zoieSystem.start();
             
            long batchVersion = 0;
            Sequece sequece=Sequeces.getSequece(cls);
     		batchVersion=sequece.getCount();
     		
            ArrayList<DataEvent<T>> eventList = new ArrayList<DataEvent<T>>();
     		for (int i = 0; i < list.size(); i++)
     		{
     				//System.out.println(cls.getName()+",batchVersion="+batchVersion);
     				T bean=list.get(i);
     				MemoryMap.set(bean.toString(),batchVersion);
	     			DataEvent<T> dataEvent=new DataEvent<T>(bean,batchVersion+"");
	     			eventList.add(dataEvent);
	     			batchVersion++;
				
			}
     		sequece.setCount(batchVersion);
     		Sequeces.update(sequece);
     		try {
     			zoieSystem.consume(eventList);
     			//zoieSystem.flushEventsToMemoryIndex(1500);
     			//zoieSystem.flushEvents(timeout)
     			//DataZoieSystem.getIndexingSystem().
     			 zoieSystem.getAdminMBean().flushToMemoryIndex();
     			 zoieSystem.getAdminMBean().flushToDiskIndex();
     		} catch (ZoieException e) {
     			e.printStackTrace();
     		}
        	
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            try {
                if (null != indexSearcher) 
                {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) 
                {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != zoieReaderList && !zoieReaderList.isEmpty()) 
                {
                   zoieSystem.returnIndexReaders(zoieReaderList);
                   zoieReaderList = null;
                }
                if (zoieSystem !=null)
                {
                	zoieSystem.shutdown();
                	zoieSystem.stop();
				}
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		
	}
	public  void delete(String key,String value)
	{
		if (key==null || (value == null)) {
			return;
		}
		
	 	List<ZoieIndexReader<IndexReader>> readerList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        ZoieSystem<IndexReader, T> zoieSystem=null;
        try {
			//get zoie system
        	// System.out.println("addDocuments start size="+list.size());
             File idxDir = new File(dirPath);
            
             try {
            	 IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_35,getAnalyzer());
				 IndexWriter indexWriter=new IndexWriter(FSDirectory.open(idxDir),config);
				 indexWriter.deleteDocuments(new Term(key,value));
				 indexWriter.close();
				 System.out.println("Deleted "+key+"="+value);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
             
             /////////////////////////////
             // my
             ZoieIndexableInterpreter<T> interpreter = new ZoieDataInterpreter<T>();
             //default
             DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
             
             // StandardAnalyzer(Version.LUCENE_35); // PerFieldAnalyzerWrapper
            
             ZoieConfig zoieConfig = new ZoieConfig();
             zoieConfig.setBatchDelay(1000);
             zoieConfig.setBatchSize(50000);
             zoieConfig.setAnalyzer(getAnalyzer());//
             zoieConfig.setSimilarity(new DefaultSimilarity());
             zoieConfig.setRtIndexing(true);
             zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
             zoieSystem.start();
             zoieSystem.getAdminMBean().flushToMemoryIndex();
                	
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            try {
                if (null != indexSearcher) 
                {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) 
                {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != readerList && !readerList.isEmpty()) 
                {
                   zoieSystem.returnIndexReaders(readerList);
                   readerList = null;
                }
                if (zoieSystem !=null)
                {
                	zoieSystem.shutdown();
                	zoieSystem.stop();
				}
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		
	}
	public  void delete(Query query)
	{
		if (query==null) {
			return;
		}
		
	 	List<ZoieIndexReader<IndexReader>> readerList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        ZoieSystem<IndexReader, T> zoieSystem=null;
        try {
			//get zoie system
        	// System.out.println("addDocuments start size="+list.size());
             File idxDir = new File(dirPath);
             try {
            	 IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_35,analyzer);
				 IndexWriter indexWriter=new IndexWriter(FSDirectory.open(idxDir),config);
				 indexWriter.deleteDocuments(query);
				 indexWriter.close();
				 System.out.println("Deleted query="+query);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
             
             /////////////////////////////
             // my
             ZoieIndexableInterpreter<T> interpreter = new ZoieDataInterpreter<T>();
             //default
             DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
             
             // StandardAnalyzer(Version.LUCENE_35); // PerFieldAnalyzerWrapper
            
             ZoieConfig zoieConfig = new ZoieConfig();
             zoieConfig.setBatchDelay(1000);
             zoieConfig.setBatchSize(50000);
             zoieConfig.setAnalyzer(getAnalyzer());//
             zoieConfig.setSimilarity(new DefaultSimilarity());
             zoieConfig.setRtIndexing(true);
             zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
             zoieSystem.start();
             zoieSystem.getAdminMBean().flushToMemoryIndex();
                	
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            try {
                if (null != indexSearcher) 
                {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) 
                {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != readerList && !readerList.isEmpty()) 
                {
                   zoieSystem.returnIndexReaders(readerList);
                   readerList = null;
                }
                if (zoieSystem !=null)
                {
                	zoieSystem.shutdown();
                	zoieSystem.stop();
				}
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		
	}
	public void update(String key,String value,T t)
	{
		if (key==null || (value==null)) {
			return;
		}
		
	 	List<ZoieIndexReader<IndexReader>> readerList = null;
        MultiReader multiReader = null;
        IndexSearcher indexSearcher = null;
        ZoieSystem<IndexReader, T> zoieSystem=null;
        try {
			//get zoie system
        	// System.out.println("addDocuments start size="+list.size());
        	TransferToDocument<T> toDocument=new TransferToDocument<T>();
        	Document document=toDocument.toDocument(t);
             File idxDir = new File(dirPath);
             try {
				IndexWriterConfig config=new IndexWriterConfig(Version.LUCENE_35,getAnalyzer());
				 IndexWriter indexWriter=new IndexWriter(FSDirectory.open(idxDir),config);
				 indexWriter.updateDocument(new Term(key,value), document);
				 indexWriter.close();
				 System.out.println("Updated "+key+"="+value);
			} catch (Exception e1) {
				e1.printStackTrace();
			}
             
             /////////////////////////////
             // my
             ZoieIndexableInterpreter<T> interpreter = new ZoieDataInterpreter<T>();
             //default
             DefaultIndexReaderDecorator decorator = new DefaultIndexReaderDecorator();
             
             // StandardAnalyzer(Version.LUCENE_35); // PerFieldAnalyzerWrapper
            
             ZoieConfig zoieConfig = new ZoieConfig();
             zoieConfig.setBatchDelay(1000);
             zoieConfig.setBatchSize(50000);
             zoieConfig.setAnalyzer(getAnalyzer());//
             zoieConfig.setSimilarity(new DefaultSimilarity());
             zoieConfig.setRtIndexing(true);
             zoieSystem = new ZoieSystem(idxDir, interpreter, decorator, zoieConfig);
             zoieSystem.start();
             zoieSystem.getAdminMBean().flushToMemoryIndex();
     	
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
            try {
                if (null != indexSearcher) 
                {
                    indexSearcher.close();
                    indexSearcher = null;
                }
                if (null != multiReader) 
                {
                    multiReader.close();
                    multiReader = null;
                }
                if (null != readerList && !readerList.isEmpty()) 
                {
                   zoieSystem.returnIndexReaders(readerList);
                   readerList = null;
                }
                if (zoieSystem !=null)
                {
                	zoieSystem.shutdown();
                	zoieSystem.stop();
				}
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
		
	}
	public void setAnalyzer(Analyzer analyzer) {
		this.analyzer = analyzer;
	}
	public Analyzer getAnalyzer() {
		if (analyzer==null) {
			analyzer=new WhitespaceAnalyzer(Version.LUCENE_35);
		}
		return analyzer;
	}
	public String getDirPath() {
		return dirPath;
	}
}
